package com.xuyuan.mybatis;

import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.SimpleExecutor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Properties;

@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class CustomExecutorInterceptor implements Interceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(CustomExecutorInterceptor.class);
    private static final String CACHE_ENABLED = "cacheEnabled";
    private Boolean isCacheEnabled = false;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 开启二级缓存和关闭二级缓存的时候，对应的Executor对象是不同的，开启二级缓存的时候是CachingExecutor
        if (isCacheEnabled) {
            CachingExecutor target = (CachingExecutor) invocation.getTarget();
            LOGGER.info("二级缓存已开启");
            LOGGER.info("Executor执行器类型为" + target.getClass().getSimpleName());
        } else {
            SimpleExecutor target = (SimpleExecutor) invocation.getTarget();
            LOGGER.info("二级缓存未开启");
            LOGGER.info("Executor执行器类型为" + target.getClass().getSimpleName());
        }

        // 也可以通过判断类型，去判断是否开启Mybatis的二级缓存
        if (invocation.getTarget() instanceof CachingExecutor) LOGGER.info("二级缓存已开启");
        else LOGGER.info("二级缓存未开启");

        Method method = invocation.getMethod();
        LOGGER.info("方法名：" + method.getName());

        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object parameter = args[1];
        RowBounds limit = (RowBounds) args[2];
        ResultHandler resultHandler = (ResultHandler) args[3];

        return invocation.proceed();
    }

    /**
     * 创建代理对象
     *
     * @param target
     */
    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    /**
     * 配置文件中为拦截器添加的配置，可以在这里读取使用。
     * 比方说是否开启二级缓存，可以在配置文件拦截器的属性里面也添加相关的配置，这里直接读取。然后可以判断执行器的类型
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        isCacheEnabled = Boolean.parseBoolean(properties.get(CACHE_ENABLED).toString());
        if (isCacheEnabled) LOGGER.info("二级缓存已开启");
        else LOGGER.info("二级缓存未开启");
    }
}
